package com.ruoyi.web.controller.tool;

import lombok.Data;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Component
public class WordUtil {

    @Value("${ruoyi.profile}")
    public String profilePath;


    private static final float DOCUMENT_WIDTH_RATIO = 1f; // 图片宽度为文档宽度的70%

    public void exportListWord(List<SendWord> sendWordList, HttpServletResponse response) throws IOException {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename=document.docx");

        // 创建文档
        XWPFDocument document = new XWPFDocument();

        sendWordList.forEach(sendWord -> {
            // 添加标题
            XWPFParagraph title = document.createParagraph();
            title.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun titleRun = title.createRun();
            titleRun.setBold(true);
            titleRun.setFontSize(16);
            // 李林在2025年7月8日获得XX大赛三等奖
            // 格式化日期
//        String formattedDate = formatDate(sendWord.getTime());
//        String titleText = sendWord.getStuName() + "在" + formattedDate + "“" + details.getRecognitionName() + "”比赛中，获得" + details.getAwardLevel();
            titleRun.setText(sendWord.getTitle());

            if (!Objects.equals(sendWord.getImage(), null)) {
                // 添加图片（从 classpath 或文件系统加载）
                String acFile = sendWord.getImage();
                // 去掉 /profile
                acFile = acFile.replace("/profile", "");
                String imagePath = profilePath + acFile;
                try {
                    addImageToDocument(document, imagePath); // 宽高单位：EMU (约 9525 = 1cm)
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        // 写出到响应流
        document.write(response.getOutputStream());
        document.close();
    }


    @Data
    public static class SendWord {
        private String title;
        private String image;
    }

    public void exportWord(SendWord sendWord, HttpServletResponse response) throws IOException {
        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setHeader("Content-Disposition", "attachment; filename=document.docx");

        // 创建文档
        XWPFDocument document = new XWPFDocument();

        // 添加标题
        XWPFParagraph title = document.createParagraph();
        title.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun titleRun = title.createRun();
        titleRun.setBold(true);
        titleRun.setFontSize(16);
        // 李林在2025年7月8日获得XX大赛三等奖
        // 格式化日期
//        String formattedDate = formatDate(sendWord.getTime());
//        String titleText = sendWord.getStuName() + "在" + formattedDate + "“" + details.getRecognitionName() + "”比赛中，获得" + details.getAwardLevel();
        titleRun.setText(sendWord.getTitle());

        if (!Objects.equals(sendWord.getImage(), null)) {
            // 添加图片（从 classpath 或文件系统加载）
            String acFile = sendWord.getImage();
            // 去掉 /profile
            acFile = acFile.replace("/profile", "");
            String imagePath = profilePath + acFile;
            addImageToDocument(document, imagePath); // 宽高单位：EMU (约 9525 = 1cm)
        }


        // 写出到响应流
        document.write(response.getOutputStream());
        document.close();
    }

    /**
     * 向文档中添加图片
     */
    /**
     * 向 Word 文档中添加图片（图片位于服务器文件系统路径）
     *
     * @param document  XWPFDocument 文档对象
     * @param imagePath 服务器上的图片完整路径，如：/opt/images/test.jpg 或 D:/images/test.jpg
     * @throws IOException
     */
    public void addImageToDocument(XWPFDocument document, String imagePath) throws IOException {
        FileInputStream imageStream = null;
        try {
            Path path = Paths.get(imagePath);
            if (!Files.exists(path)) {
                throw new IOException("图片文件未找到: " + imagePath);
            }

            imageStream = new FileInputStream(path.toFile());
            byte[] imageBytes = IOUtils.toByteArray(imageStream);
            BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageBytes));

            if (image == null) {
                throw new IOException("无法读取图片格式: " + imagePath);
            }

            int originalWidth = image.getWidth();
            int originalHeight = image.getHeight();
            float aspectRatio = (float) originalHeight / originalWidth;

            // 获取Word页面的实际可用宽度（A4页面宽度约为9072 twips）
            int documentWidthTwips = 9072;
            // 设定最大宽度比例为80%
            int maxWidthTwips = (int) (documentWidthTwips * 0.8);

            // 计算目标宽度，并设置最小宽度限制
            int targetWidthTwips = 200;

            // 根据宽高比计算目标高度
            int targetHeightTwips = (int) (targetWidthTwips * aspectRatio);

            // 转换为EMU单位
            int targetWidthEMU = Units.toEMU(targetWidthTwips);
            int targetHeightEMU = Units.toEMU(targetHeightTwips);

            // 推断图片类型
            String mimeType = Files.probeContentType(path);
            int pictureType = XWPFDocument.PICTURE_TYPE_JPEG;
            if ("image/png".equals(mimeType)) pictureType = XWPFDocument.PICTURE_TYPE_PNG;
            else if ("image/gif".equals(mimeType)) pictureType = XWPFDocument.PICTURE_TYPE_GIF;

            // 创建段落并居中
            XWPFParagraph imageParagraph = document.createParagraph();
            imageParagraph.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun imageRun = imageParagraph.createRun();

            imageRun.addPicture(
                    new ByteArrayInputStream(imageBytes),
                    pictureType,
                    imagePath.substring(imagePath.lastIndexOf("/") + 1), // 文件名
                    targetWidthEMU,
                    targetHeightEMU
            );

        } catch (Exception e) {
            throw new IOException("无法处理图片: " + imagePath, e);
        } finally {
            if (imageStream != null) {
                try {
                    imageStream.close();
                } catch (IOException e) {
                    // 忽略关闭异常
                }
            }
        }
    }

    public static String formatDate(Date date) {
        if (date == null) {
            return ""; // 或返回null，根据实际需求处理
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(date);
    }

    /**
     * 添加标题（居中加粗）
     */
    public void addTitle(XWPFDocument document, String text) {
        XWPFParagraph p = document.createParagraph();
        p.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun r = p.createRun();
        r.setText(text);
        r.setFontSize(16);
        r.setBold(true);
        r.setFontFamily("宋体");
    }

    /**
     * 添加普通段落
     */
    public void addParagraph(XWPFDocument document, String text) {
        XWPFParagraph p = document.createParagraph();
        XWPFRun r = p.createRun();
        r.setText(text);
        r.setFontSize(12);
        r.setFontFamily("宋体");
    }

    /**
     * 添加空行
     *
     * @param document
     * @param height
     */
    public void addEmptyLine(XWPFDocument document, int height) {
        XWPFParagraph paragraph = document.createParagraph();
        // 设置段前和段后间距来控制空行的高度
        paragraph.setSpacingBefore(height);
        paragraph.setSpacingAfter(0);
    }

    /**
     * 小一点且居中文字的方法
     */
    public void addSmallCenteredText(XWPFDocument document, String text, int fontSize) {
        XWPFParagraph paragraph = document.createParagraph();
        // 设置文本居中
        paragraph.setAlignment(ParagraphAlignment.CENTER);

        // 创建运行并设置文本
        XWPFRun run = paragraph.createRun();
        run.setText(text);

        // 设置字体大小
        run.setFontSize(fontSize);
    }

    /**
     * 添加表格
     */
    public void addTable(XWPFDocument document, List<List<String>> tableData, List<List<Integer>> regions) {
        if (tableData == null || tableData.isEmpty()) return;

        XWPFTable table = document.createTable();
        // 设置表格宽度为 100%（撑满页面）
        CTTblWidth tblWidth = table.getCTTbl().addNewTblPr().addNewTblW();
        tblWidth.setType(STTblWidth.DXA);
        tblWidth.setW(BigInteger.valueOf(9900)); // 9900 twips ≈ 100%
        table.setTableAlignment(TableRowAlign.CENTER);

        // 复用第一行并填充数据
        fillRow(table.getRow(0), tableData.get(0));

        // 添加剩余行并填充数据
        for (int i = 1; i < tableData.size(); i++) {
            fillRow(table.createRow(), tableData.get(i));
        }

        regions.forEach(item -> {
            Integer a = item.get(0); // 3
            Integer b = item.get(1) - 1; // 8
            Integer c = item.get(2); // 3
            Integer d = item.get(3); // 5
            mergeCellsVerticallyWithAlignment(table, 0, a, b);
            for (int i = 0; i < d; i++) {
                mergeCellsHorizontally(table, i + c, 1, 3);
            }
        });
    }

    /**
     * 添加表格
     */
    public void addTableByCombined(XWPFDocument document, List<List<String>> tableData) {
        if (tableData == null || tableData.isEmpty()) return;

        XWPFTable table = document.createTable();
        // 设置表格宽度为 100%（撑满页面）
        CTTblWidth tblWidth = table.getCTTbl().addNewTblPr().addNewTblW();
        tblWidth.setType(STTblWidth.DXA);
        tblWidth.setW(BigInteger.valueOf(9900)); // 9900 twips ≈ 100%
        table.setTableAlignment(TableRowAlign.CENTER);

        // 复用第一行并填充数据
        fillRow(table.getRow(0), tableData.get(0));

        // 添加剩余行并填充数据
        for (int i = 1; i < tableData.size(); i++) {
            fillRow(table.createRow(), tableData.get(i));
        }
        mergeCellsVerticallyWithAlignment(table, 0, 0, tableData.size() - 1);
        for (int i = 0; i < tableData.size(); i++) {
            mergeCellsHorizontally(table, i, 1, 3);
        }
    }

    /**
     * 水平合并指定行的连续列
     *
     * @param table    表格对象
     * @param rowIndex 要合并的行索引（从0开始）
     * @param startCol 合并的起始列索引（从0开始）
     * @param endCol   合并的结束列索引（从0开始）
     */
    private void mergeCellsHorizontally(XWPFTable table, int rowIndex, int startCol, int endCol) {
        // 参数校验：确保起始列小于结束列，且行索引有效
        if (table == null || startCol >= endCol || rowIndex < 0 || rowIndex >= table.getRows().size()) {
            return;
        }

        XWPFTableRow row = table.getRow(rowIndex);

        // 处理起始单元格
        CTTcPr startTcPr = row.getCell(startCol).getCTTc().getTcPr();
        if (startTcPr == null) {
            startTcPr = row.getCell(startCol).getCTTc().addNewTcPr();
        }
        startTcPr.addNewHMerge().setVal(STMerge.RESTART);

        // 处理中间和结束单元格
        for (int colIndex = startCol + 1; colIndex <= endCol; colIndex++) {
            // 确保单元格存在
            if (colIndex >= row.getTableCells().size()) {
                row.createCell();
            }

            CTTcPr tcPr = row.getCell(colIndex).getCTTc().getTcPr();
            if (tcPr == null) {
                tcPr = row.getCell(colIndex).getCTTc().addNewTcPr();
            }
            tcPr.addNewHMerge().setVal(STMerge.CONTINUE);

            // 清空被合并单元格的内容
            row.getCell(colIndex).setText("");
        }
    }

    /**
     * 垂直合并指定列的连续行，并设置内容居中
     *
     * @param table    表格对象
     * @param column   列索引（从0开始）
     * @param startRow 起始行索引
     * @param endRow   结束行索引
     */
    public void mergeCellsVerticallyWithAlignment(XWPFTable table, int column, int startRow, int endRow) {
        if (startRow >= endRow || table == null) {
            return; // 无效参数处理
        }

        for (int rowIndex = startRow; rowIndex <= endRow; rowIndex++) {
            XWPFTableRow row = table.getRow(rowIndex);
            XWPFTableCell cell = row.getCell(column);
            if (cell == null) {
                cell = row.createCell(); // 确保单元格存在
            }

            // 1. 设置垂直合并属性
            CTTcPr tcPr = cell.getCTTc().getTcPr() != null ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr();
            if (rowIndex == startRow) {
                // 起始行：标记合并开始
                tcPr.addNewVMerge().setVal(STMerge.RESTART);
            } else {
                // 后续行：标记合并延续
                tcPr.addNewVMerge().setVal(STMerge.CONTINUE);
                cell.setText(""); // 清空被合并单元格内容
            }

            // 2. 设置单元格垂直对齐（上下居中）
            CTVerticalJc vAlign = tcPr.addNewVAlign();
            vAlign.setVal(STVerticalJc.CENTER); // 垂直居中

            // 3. 设置段落水平居中（仅起始行需要，其他行已清空）
            if (rowIndex == startRow) {
                for (XWPFParagraph paragraph : cell.getParagraphs()) {
                    paragraph.setAlignment(ParagraphAlignment.CENTER); // 水平居中
                }
            }
        }
    }

    // 辅助方法：安全填充一行
    private void fillRow(XWPFTableRow row, List<String> data) {
        for (int i = 0; i < data.size(); i++) {
            XWPFTableCell cell = i < row.getTableCells().size() ? row.getCell(i) : row.createCell();
            cell.setText(data.get(i));
            // 设置段落间距，增加行间距
            for (XWPFParagraph paragraph : cell.getParagraphs()) {
                paragraph.setSpacingBefore(100); // 在段落前添加间距，单位是 twips (1/20 of a point)
                paragraph.setSpacingAfter(100); // 在段落后添加间距
                paragraph.setAlignment(ParagraphAlignment.CENTER); // ✅ 水平居中
            }
        }
    }
}
